﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Reflection;
using System.Windows.Forms;
using Spring.Context;
using Spring.Context.Support;
using Bamboo.Core.Common.Reflection;
using System.IO;


namespace TinyERP.Framework.Plugin
{
    public class PluginManager
    {
        private static PluginManager instance;
        public string PluginPath { get; set; }
        private PluginManager()
        {

        }
        public static PluginManager GetInstance()
        {
            if (instance == null)
            {
                instance = new PluginManager();
            }
            return instance;
        }

        public void LoadPlugins()
        {
            ApplicationConfiguration applicationConfig = ApplicationConfiguration.GetInstance();
            this.PluginPath = applicationConfig.PluginPath;
            LoadModuleAssemblies(applicationConfig);
        }

        private void RegisterModuleContextObjectInAssembly(string assemblyKey)
        {
            Assembly assembly = GetAssemblyOfModule(assemblyKey);
            string typeNameOfPluginContext = assemblyKey + ".PluginContextImp";
            Type pluginContextType = assembly.GetType(typeNameOfPluginContext);
            PluginContext pluginContextInstance = (PluginContext) Activator.CreateInstance(pluginContextType);
            pluginContextInstance.RegisterModuleObjects();
        }

        private void LoadModuleAssemblies(ApplicationConfiguration applicationConfig)
        {
            IList<Module> moduleList = applicationConfig.Modules;
            foreach (Module module in moduleList)
            {
                LoadModuleDLL(module.Assembly);
                RegisterModuleContextObjectInAssembly(module.Assembly);
            }
            ServiceLocator.GetInstance().RefreshContext();

        }

        private string GetAssemblyNameFromUIClass(string uiClass)
        {
            if (string.IsNullOrEmpty(uiClass))
            {
                return null;
            }
            string[] partsOfUIClassName = uiClass.Split(',');
            if (partsOfUIClassName.Length < 1)
            {
                return null;
            }
            string assemblyName = partsOfUIClassName[1];
            assemblyName = assemblyName.Trim();
            return assemblyName;
        }

        private string GetTypeNameFromUIClass(string uiClass)
        {
            if (string.IsNullOrEmpty(uiClass))
            {
                return null;
            }
            string[] partsOfUIClassName = uiClass.Split(',');
            if (partsOfUIClassName.Length < 1)
            {
                return null;
            }
            string typeName = partsOfUIClassName[0];
            typeName = typeName.Trim();
            return typeName;
        }

        public Assembly GetAssemblyOfModule(string moduleName)
        {
            Assembly[] assArray = AppDomain.CurrentDomain.GetAssemblies();
            foreach (Assembly assembly in assArray)
            {
                if (assembly.GetName().Name == moduleName)
                {
                    return assembly;
                }
            }
            return null;
        }

        public UserControl CreateForm(string uiClass)
        {
            string assemblyName = GetAssemblyNameFromUIClass(uiClass);
            string typeName = GetTypeNameFromUIClass(uiClass);
            Assembly assembly = GetAssemblyOfModule(assemblyName);
            if (assembly == null)
            {
                return null;
            }
            Type formType = assembly.GetType(typeName);
            UserControl formInstance = null;
            if (formType != null)
            {
                formInstance = (UserControl) Activator.CreateInstance(formType);
            }
            return formInstance;
        }



        private void LoadModuleDLL(string assemblyName)
        {
            if (ApplicationConfiguration.GetInstance().ApplicationMode == "Plugin")
            {
                AppDomain.CurrentDomain.AppendPrivatePath(PluginPath + "/" + assemblyName + "/");
            }
            AppDomain.CurrentDomain.Load(assemblyName);
        }
    }
}
